package com.ly.heart.service.impl;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;


import com.ly.common.core.domain.AjaxResult;
import com.ly.common.core.domain.entity.SysDept;
import com.ly.common.core.domain.entity.SysUser;
import com.ly.common.utils.DateUtils;
import com.ly.common.utils.SecurityUtils;
import com.ly.common.utils.StringUtils;
import com.ly.common.utils.erp.*;
import com.ly.heart.domain.*;
import com.ly.heart.domain.dto.KingOtherInboundQueryDto;
import com.ly.heart.domain.dto.KingRealInventoryQueryDto;
import com.ly.heart.domain.dto.StartProcessDto;
import com.ly.common.core.domain.ActCurrentTaskVo;
import com.ly.heart.domain.vo.OtherInboundVo;
import com.ly.heart.mapper.KingOtherInboundMapper;
import com.ly.heart.service.*;
import com.ly.heart.util.ChineseToPinyin;
import com.ly.heart.util.CurrentUserUtil;
import com.ly.system.service.ISysDeptService;
import com.ly.system.service.ISysUserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;

/**
 * 金蝶-其他入库单Service业务层处理
 *
 * @author cxl
 * @date 2024-08-03
 */
@Service
public class KingOtherInboundServiceImpl extends ServiceImpl<KingOtherInboundMapper,KingOtherInboundEntity> implements IKingOtherInboundService {

    @Resource
    private KingOtherInboundMapper kingOtherInboundMapper;
    @Resource
    private ISysDeptService sysDeptService;
    @Resource
    private IActModelService actModelService;
    @Resource
    private IActTaskCommentService actTaskCommentService;
    @Resource
    private IKingOtherInboundMaterialService kingOtherInboundMaterialService;
    @Resource
    private IKingOtherInboundMaterialDetailService kingOtherInboundMaterialDetailService;
    @Resource
    private IKingOtherInboundMaterialDetailSerialService kingOtherInboundMaterialDetailSerialService;
    @Resource
    private IKingRealInventoryService kingRealInventoryService;
    @Resource
    private ISupplierService supplierService;
    @Resource
    private ISysUserService sysUserService;
    @Resource
    private IKingBaseBusinessGroupDetailService kingBaseBusinessGroupDetailService;
    @Resource
    private IKingBaseMeteringUnitService kingBaseMeteringUnitService;
    @Resource
    private IWarehouseService warehouseService;



    @Override
    public AjaxResult getOtherInboundPageList(KingOtherInboundQueryDto queryDto){
        List<OtherInboundVo> list = kingOtherInboundMaterialService.getOtherInboundPageList(queryDto);
        if(!CollectionUtils.isEmpty(list)){
            list.forEach(otherInboundVo -> {
                ActTaskCommentEntity actTaskCommentEntity = actTaskCommentService.queryLastComment(otherInboundVo.getInstanceId());
                if ( actTaskCommentEntity != null ) {
                    otherInboundVo.setApprovedUser ( actTaskCommentEntity.getApprovedUser () );
                    otherInboundVo.setRemark ( actTaskCommentEntity.getRemark () );
                }
                ActCurrentTaskVo currentTaskVo = actModelService.getCurrentTaskByInstanceId(otherInboundVo.getInstanceId());
                Optional.ofNullable(currentTaskVo).ifPresent(otherInboundVo::setCurrentTask);
            });
        }
        Page<OtherInboundVo> page = new Page<>(queryDto.getPage(),queryDto.getLimit());
        return AjaxResult.success(ReturnPage.getReturnPage(page, list));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult draft(KingOtherInboundEntity kingOtherInbound){
        if(StringUtils.isEmpty(kingOtherInbound.getId())){
            String otherInboundId = SnowflakeIdWorker.getInstance().nextStringId();
            Date nowDate = DateUtils.getNowDate();
            String userId = SecurityUtils.getLoginUser().getUser().getUserId();
            //设置其他入库单基本信息
            kingOtherInbound.setId(otherInboundId).setCreateTime(nowDate).setUserId(userId);
            //其他入库单单号生成
            if (StringUtils.isEmpty(kingOtherInbound.getDocCode())) {
                String companyId = CurrentUserUtil.getCompanyId();
                SysDept sysDept = sysDeptService.getById(companyId);
                int count = this.count();
                String countStr = String.format("%06d", count);
                String firstLetter = ChineseToPinyin.getFirstLetter(sysDept.getDeptName());
                String docCode = firstLetter.concat("_QTRK_").concat(countStr);
                kingOtherInbound.setDocCode(docCode);
            }
            //保存物料信息
            if (!CollectionUtils.isEmpty(kingOtherInbound.getMaterialLists())){
                saveMaterialAndDetail(kingOtherInbound);
            }
            //流程状态：暂存
            kingOtherInbound.setState(ConstUtil.STATE_IN_DRAFT);
            boolean save = this.save(kingOtherInbound);
            if(save){
                return AjaxResult.success("暂存其他入库单成功！",kingOtherInbound.getId());
            }
            return AjaxResult.error("暂存其他入库单失败！");
        }else{
            return update(kingOtherInbound);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult submit(KingOtherInboundEntity kingOtherInbound){
        if ( StringUtils.isBlank ( kingOtherInbound.getId () ) ) {
            return AjaxResult.error ("请先暂存该单据！");
        }
        if(Objects.isNull(kingOtherInbound.getModelId())){
            return AjaxResult.error("审批流程modelId不能为空！");
        }
        if (CollectionUtils.isEmpty(kingOtherInbound.getMaterialLists())) {
            return AjaxResult.error("物料信息不能为空！");
        }
        //先删除暂存时保存的物料以及明细信息
        removeMaterialAndDetail(kingOtherInbound.getId());
        //保存物料以及明细信息
        saveMaterialAndDetail(kingOtherInbound);
        //启动审批流程
        StartProcessDto startDto = new StartProcessDto().setBusinessId(kingOtherInbound.getId()).setBusinessType(kingOtherInbound.getBusinessType()).setModelId(kingOtherInbound.getModelId());
        startDto.setBusinessName("其他入库单_".concat(kingOtherInbound.getDocCode()));
        String instanceId = actModelService.startProcess(startDto);
        kingOtherInbound.setState(ConstUtil.STATE_IN_PROCESS).setInstanceId(instanceId);
        boolean updated = this.updateById(kingOtherInbound);
        if ( !updated ) {
            return AjaxResult.error( "提交其他入库单失败！!" );
        }
        return AjaxResult.success ( "提交其他入库单成功!" );
    }

    @Override
    public AjaxResult update(KingOtherInboundEntity kingOtherInbound) {
        if(StringUtils.isEmpty(kingOtherInbound.getId())){
            return AjaxResult.error("其他入库单id不能为空！");
        }
        //先删除暂存时保存的物料以及明细信息
        removeMaterialAndDetail(kingOtherInbound.getId());
        if (!CollectionUtils.isEmpty(kingOtherInbound.getMaterialLists())){
            saveMaterialAndDetail(kingOtherInbound);
        }
        boolean updated = this.updateById(kingOtherInbound);
        if ( !updated ) {
            return AjaxResult.error( "修改其他入库单失败!" );
        }
        return AjaxResult.success ( "修改其他入库单成功!",kingOtherInbound.getId());
    }

    /**
     * 保存物料明细以及其他信息
     * @param kingOtherInbound
     */
    private void saveMaterialAndDetail(KingOtherInboundEntity kingOtherInbound){
        List<KingOtherInboundMaterialEntity> materialLists = kingOtherInbound.getMaterialLists();
        materialLists.forEach(otherInboundMaterial -> {
            String otherInboundMaterialId = SnowflakeIdWorker.getInstance().nextStringId();
            otherInboundMaterial.setId(otherInboundMaterialId);
            otherInboundMaterial.setOtherInboundId(kingOtherInbound.getId());
            otherInboundMaterial.setUserId(kingOtherInbound.getUserId());
            otherInboundMaterial.setCreateTime(kingOtherInbound.getCreateTime());
            if(StringUtils.isEmpty(otherInboundMaterial.getBatchNum())){
                otherInboundMaterial.setBatchNum(BatchNumberGenerator.generateBatchNumber());
            }
            boolean otherInboundMaterialFlag = kingOtherInboundMaterialService.save(otherInboundMaterial);
            if(!otherInboundMaterialFlag){
                throw new RuntimeException("新增其他入库单物料信息失败！");
            }
            KingOtherInboundMaterialDetailEntity otherInboundMaterialDetail = otherInboundMaterial.getMaterialDetail();
            String otherInboundMaterialDetailId = SnowflakeIdWorker.getInstance().nextStringId();
            otherInboundMaterialDetail.setId(otherInboundMaterialDetailId);
            otherInboundMaterialDetail.setOtherInboundId(kingOtherInbound.getId());
            otherInboundMaterialDetail.setOtherInboundMaterialId(otherInboundMaterialId);
            otherInboundMaterialDetail.setUserId(otherInboundMaterial.getUserId());
            otherInboundMaterialDetail.setCreateTime(otherInboundMaterial.getCreateTime());
            boolean otherInboundMaterialDetailFlag = kingOtherInboundMaterialDetailService.save(otherInboundMaterialDetail);
            if(!otherInboundMaterialDetailFlag){
                throw new RuntimeException("新增其他入库单物料明细失败！");
            }
            List<KingOtherInboundMaterialDetailSerialEntity> materialDetailSerials = otherInboundMaterialDetail.getMaterialDetailSerials();
            if(!CollectionUtils.isEmpty(materialDetailSerials)){
                materialDetailSerials.forEach(materialDetailSerial -> {
                    materialDetailSerial.setId(SnowflakeIdWorker.getInstance().nextStringId());
                    materialDetailSerial.setOtherInboundId(kingOtherInbound.getId());
                    materialDetailSerial.setOtherInboundMaterialId(otherInboundMaterialId);
                    materialDetailSerial.setMaterialDetailId(otherInboundMaterialDetailId);
                    materialDetailSerial.setUserId(kingOtherInbound.getUserId());
                    materialDetailSerial.setCreateTime(kingOtherInbound.getCreateTime());
                    kingOtherInboundMaterialDetailSerialService.save(materialDetailSerial);
                });
            }
        });
    }


    @Override
    public void updateRealTimeInventory(List<KingOtherInboundMaterialEntity> materialLists) {
        if(CollectionUtils.isEmpty(materialLists)){
            throw new RuntimeException("其他入库单物料明细为空，更新即时库存失败！");
        }
        materialLists.forEach(otherInboundMaterial -> {
            //查询即时库存
            KingRealInventoryQueryDto realInventoryQueryDto = new KingRealInventoryQueryDto();
            realInventoryQueryDto.setMaterialCode(otherInboundMaterial.getMaterialCode());
            realInventoryQueryDto.setWarehouseCode(otherInboundMaterial.getReceiveWarehouseCode());
            KingRealInventoryEntity realInventory = kingRealInventoryService.getRealInventoryByMaterialAndWarehouseAndPosition(realInventoryQueryDto);
            //如果仓库里此物品不存在，则新增
            if(Objects.isNull(realInventory)){
                KingRealInventoryEntity saveRealInventory = new KingRealInventoryEntity();
                saveRealInventory.setId(SnowflakeIdWorker.getInstance().nextStringId());
                saveRealInventory.setMaterialCode(otherInboundMaterial.getMaterialCode());
                saveRealInventory.setWarehouseCode(otherInboundMaterial.getReceiveWarehouseCode());
                saveRealInventory.setInventoryNum(otherInboundMaterial.getReceiptsNum());
                saveRealInventory.setBomVersion(Optional.ofNullable(otherInboundMaterial.getMaterialDetail().getBomVer()).orElse(new KingOtherInboundMaterialDetailEntity().getBomVer()));
                saveRealInventory.setWarehousePosition(otherInboundMaterial.getWarehousePosition());
                saveRealInventory.setCreateBy(SecurityUtils.getLoginUser().getUser().getUserId());
                saveRealInventory.setCreateTime(DateUtils.getNowDate());
                boolean save = kingRealInventoryService.save(saveRealInventory);
                if(!save){
                    throw new RuntimeException("更新即时库存失败！");
                }
            }else {
                String inventoryNum = realInventory.getInventoryNum();
                String sumResult = CommonUtil.sumStr(inventoryNum, otherInboundMaterial.getReceiptsNum(), 2);
                KingRealInventoryEntity updateRealInventory = new KingRealInventoryEntity();
                updateRealInventory.setId(realInventory.getId());
                updateRealInventory.setInventoryNum(sumResult);
                updateRealInventory.setUpdateBy(SecurityUtils.getLoginUser().getUser().getUserId());
                updateRealInventory.setUpdateTime(DateUtils.getNowDate());
                boolean updated = kingRealInventoryService.updateById(updateRealInventory);
                if(!updated){
                    throw new RuntimeException("更新即时库存失败！");
                }
            }
        });
    }

    /**
     * 查询金蝶-其他入库单
     *
     * @param id 金蝶-其他入库单ID
     * @return 金蝶-其他入库单
     */
    @Override
    public KingOtherInboundEntity selectKingOtherInboundEntityById(String id)
    {
        KingOtherInboundEntity kingOtherInbound = kingOtherInboundMapper.selectKingOtherInboundEntityById(id);
        if(Objects.nonNull(kingOtherInbound)){
            //库存组织
            if(StringUtils.isNotEmpty(kingOtherInbound.getInventoryOrg())){
                SysDept inventoryOrg = sysDeptService.getOne(new LambdaQueryWrapper<SysDept>().eq(SysDept::getDeptCode, kingOtherInbound.getInventoryOrg()));
                Optional.ofNullable(inventoryOrg).ifPresent(i -> {
                    kingOtherInbound.setInventoryOrgName(i.getDeptName());
                });
            }
            //供应商
            SupplierEntity supplierEntity = supplierService.getOne(new LambdaQueryWrapper<SupplierEntity>().eq(SupplierEntity::getSupplierCode, kingOtherInbound.getSupplierCode()));
            Optional.ofNullable(supplierEntity).ifPresent(s -> {
                kingOtherInbound.setSupplierName(s.getSupplierName());
            });
            //部门名称
            if(StringUtils.isNotEmpty(kingOtherInbound.getDeptCode())){
                SysDept deptCode = sysDeptService.getOne(new LambdaQueryWrapper<SysDept>().eq(SysDept::getDeptCode, kingOtherInbound.getDeptCode()));
                Optional.ofNullable(deptCode).ifPresent(d -> {
                    kingOtherInbound.setDeptName(d.getDeptName());
                });
            }
            //验收员名称
            if(StringUtils.isNotEmpty(kingOtherInbound.getInspector())){
                SysUser inspectorName = sysUserService.getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserCode, kingOtherInbound.getInspector()));
                Optional.ofNullable(inspectorName).ifPresent(i -> {
                    kingOtherInbound.setInspectorName(i.getUserName());
                });
            }
            //仓管员名称
            if(StringUtils.isNotEmpty(kingOtherInbound.getManagementBy())){
                SysUser managementBy = sysUserService.getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserCode, kingOtherInbound.getManagementBy()));
                Optional.ofNullable(managementBy).ifPresent(m -> {
                    kingOtherInbound.setManagementByName(m.getUserName());
                });
            }
            //库存组名称
            if(StringUtils.isNotEmpty(kingOtherInbound.getInventoryGroup())){
                KingBaseBusinessGroupDetailEntity inventoryGroup = kingBaseBusinessGroupDetailService.getOne(new LambdaQueryWrapper<KingBaseBusinessGroupDetailEntity>().eq(KingBaseBusinessGroupDetailEntity::getBusinessCode, kingOtherInbound.getInventoryGroup()));
                Optional.ofNullable(inventoryGroup).ifPresent(i -> {
                    kingOtherInbound.setInventoryGroupName(i.getBusinessName());
                });
            }
            List<KingOtherInboundMaterialEntity> kingOtherInboundMaterials = kingOtherInboundMaterialService.list(new LambdaQueryWrapper<KingOtherInboundMaterialEntity>().eq(KingOtherInboundMaterialEntity::getOtherInboundId, kingOtherInbound.getId()));
            if(!CollectionUtils.isEmpty(kingOtherInboundMaterials)){
                kingOtherInboundMaterials.forEach(otherInboundMaterial -> {
                    //单位名称
                    if(StringUtils.isNotEmpty(otherInboundMaterial.getUnit())){
                        KingBaseMeteringUnitEntity meteringUnitEntity = kingBaseMeteringUnitService.getOne(new LambdaQueryWrapper<KingBaseMeteringUnitEntity>().eq(KingBaseMeteringUnitEntity::getMeteringUnitCode, otherInboundMaterial.getUnit()));
                        Optional.ofNullable(meteringUnitEntity).ifPresent(m -> {
                            otherInboundMaterial.setUnitName(m.getMeteringUnitName());
                        });
                    }
                    //收货仓库
                    if(StringUtils.isNotEmpty(otherInboundMaterial.getReceiveWarehouseCode())){
                        WarehouseEntity warehouseEntity = warehouseService.getOne(new LambdaQueryWrapper<WarehouseEntity>().eq(WarehouseEntity::getWareCode, otherInboundMaterial.getReceiveWarehouseCode()));
                        Optional.ofNullable(warehouseEntity).ifPresent(w -> {
                            otherInboundMaterial.setReceiveWarehouseName(w.getWareName());
                        });
                    }
                    KingOtherInboundMaterialDetailEntity kingOtherInboundMaterialDetail = kingOtherInboundMaterialDetailService.getOne(new LambdaQueryWrapper<KingOtherInboundMaterialDetailEntity>().eq(KingOtherInboundMaterialDetailEntity::getOtherInboundId, kingOtherInbound.getId()).eq(KingOtherInboundMaterialDetailEntity::getOtherInboundMaterialId, otherInboundMaterial.getId()));
                    if(Objects.nonNull(kingOtherInboundMaterialDetail)){
                        List<KingOtherInboundMaterialDetailSerialEntity> kingOtherInboundMaterialDetailSerialList = kingOtherInboundMaterialDetailSerialService.list(new LambdaQueryWrapper<KingOtherInboundMaterialDetailSerialEntity>().eq(KingOtherInboundMaterialDetailSerialEntity::getOtherInboundId, kingOtherInbound.getId()).eq(KingOtherInboundMaterialDetailSerialEntity::getOtherInboundMaterialId, otherInboundMaterial.getId()).eq(KingOtherInboundMaterialDetailSerialEntity::getMaterialDetailId, kingOtherInboundMaterialDetail.getId()));
                        kingOtherInboundMaterialDetail.setMaterialDetailSerials(kingOtherInboundMaterialDetailSerialList);
                    }
                    otherInboundMaterial.setMaterialDetail(kingOtherInboundMaterialDetail);
                });
            }
        }
        return kingOtherInbound;
    }

    /**
     * 查询金蝶-其他入库单列表
     *
     * @param kingOtherInboundEntity 金蝶-其他入库单
     * @return 金蝶-其他入库单
     */
    @Override
    public List<KingOtherInboundEntity> selectKingOtherInboundEntityList(KingOtherInboundEntity kingOtherInboundEntity)
    {
        return kingOtherInboundMapper.selectKingOtherInboundEntityList(kingOtherInboundEntity);
    }

    /**
     * 新增金蝶-其他入库单
     *
     * @param kingOtherInboundEntity 金蝶-其他入库单
     * @return 结果
     */
    @Override
    public int insertKingOtherInboundEntity(KingOtherInboundEntity kingOtherInboundEntity)
    {
        kingOtherInboundEntity.setCreateTime(DateUtils.getNowDate());
        return kingOtherInboundMapper.insertKingOtherInboundEntity(kingOtherInboundEntity);
    }

    /**
     * 修改金蝶-其他入库单
     *
     * @param kingOtherInboundEntity 金蝶-其他入库单
     * @return 结果
     */
    @Override
    public int updateKingOtherInboundEntity(KingOtherInboundEntity kingOtherInboundEntity)
    {
        return kingOtherInboundMapper.updateKingOtherInboundEntity(kingOtherInboundEntity);
    }

    private void removeMaterialAndDetail(String id){
        kingOtherInboundMaterialService.remove(new LambdaQueryWrapper<KingOtherInboundMaterialEntity>().eq(KingOtherInboundMaterialEntity::getOtherInboundId,id));
        kingOtherInboundMaterialDetailService.remove(new LambdaQueryWrapper<KingOtherInboundMaterialDetailEntity>().eq(KingOtherInboundMaterialDetailEntity::getOtherInboundId,id));
        kingOtherInboundMaterialDetailSerialService.remove(new LambdaQueryWrapper<KingOtherInboundMaterialDetailSerialEntity>().eq(KingOtherInboundMaterialDetailSerialEntity::getOtherInboundId,id));
    }

    /**
     * 批量删除金蝶-其他入库单
     *
     * @param ids 需要删除的金蝶-其他入库单ID
     * @return 结果
     */
    @Override
    public int deleteKingOtherInboundEntityByIds(String[] ids)
    {
        for(String id : ids){
            removeMaterialAndDetail(id);
        }
        return kingOtherInboundMapper.deleteKingOtherInboundEntityByIds(ids);
    }

    /**
     * 删除金蝶-其他入库单信息
     *
     * @param id 金蝶-其他入库单ID
     * @return 结果
     */
    @Override
    public int deleteKingOtherInboundEntityById(String id)
    {
        removeMaterialAndDetail(id);
        return kingOtherInboundMapper.deleteKingOtherInboundEntityById(id);
    }
}
